/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>
*/
package cmd

import (
	"barge/app"
	"barge/cmd/center"
	"barge/cmd/registry"
	"barge/cmd/rule"
	"github.com/pkg/errors"
	"github.com/rs/zerolog"
	"github.com/rs/zerolog/log"
	"github.com/spf13/cobra"
	"github.com/spf13/viper"
	"os"
)

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
	Use:   "barge",
	Short: "镜像传输工具",
	Long:  `镜像传输工具，用于将镜像从一个仓库传输到另一个仓库，或者从一个仓库传输到中转服务器，再从中转服务器传输到另一个仓库`,
	Args: func(cmd *cobra.Command, args []string) error {
		if runOpt.Images == nil {
			runOpt.Images = args
		}
		if len(runOpt.Images) == 0 {
			return errors.New("镜像列表不能为空")
		}
		return nil
	},
	Run: func(cmd *cobra.Command, args []string) {
		if runOpt.Quiet {
			zerolog.SetGlobalLevel(zerolog.InfoLevel)
		}
		runner, err := app.NewRunner(runOpt)
		if err != nil {
			log.Err(err).Send()
			return
		}
		err = runner.Run()
		if err != nil {
			log.Err(err).Send()
			return
		}
	},
}

// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
	err := rootCmd.Execute()
	if err != nil {
		os.Exit(1)
	}
}

var runOpt = new(app.RunOption)

func init() {
	rootCmd.Flags().BoolP("toggle", "", false, "Help message for toggle")

	rootCmd.PersistentFlags().String("config", "", "config file")
	_ = viper.BindPFlag("configPath", rootCmd.PersistentFlags().Lookup("config"))
	rootCmd.PersistentFlags().BoolP("interactive", "x", false, "启用交互模式")
	_ = viper.BindPFlag("interactive", rootCmd.PersistentFlags().Lookup("interactive"))

	rootCmd.Flags().BoolVarP(&runOpt.Quiet, "quiet", "q", false, "静默模式")

	rootCmd.Flags().StringVarP(&runOpt.Center, "center", "c", "", "中转服务名称")
	rootCmd.Flags().StringVarP(&runOpt.CenterHost, "center-host", "", "", "中转服务主机地址")
	rootCmd.Flags().IntVarP(&runOpt.CenterPort, "center-port", "", 0, "中转服务主机端口")
	rootCmd.Flags().StringVarP(&runOpt.CenterUsername, "center-username", "", "", "中转服务主机用户")
	rootCmd.Flags().StringVarP(&runOpt.CenterPassword, "center-password", "", "", "中转服务主机密码")
	rootCmd.MarkFlagsOneRequired("center", "center-host")
	rootCmd.MarkFlagsRequiredTogether("center-host", "center-port", "center-username", "center-password")

	rootCmd.Flags().StringVarP(&runOpt.Registry, "registry", "r", "", "镜像仓库名称")
	rootCmd.Flags().StringVarP(&runOpt.RegistryAddr, "registry-addr", "", "", "镜像仓库地址")
	rootCmd.Flags().StringVarP(&runOpt.RegistryUsername, "registry-username", "", "", "镜像仓库用户名")
	rootCmd.Flags().StringVarP(&runOpt.RegistryPassword, "registry-password", "", "", "镜像仓库密码")
	rootCmd.Flags().StringArrayVarP(&runOpt.Architectures, "arch", "", nil, "镜像仓库架构[amd64,arm64]")
	rootCmd.MarkFlagsOneRequired("registry", "registry-addr")
	rootCmd.MarkFlagsRequiredTogether("registry-addr", "registry-username", "registry-password", "center-password")
	rootCmd.MarkFlagsMutuallyExclusive("registry", "registry-addr")

	rootCmd.Flags().StringArrayVarP(&runOpt.Images, "images", "i", nil, "传输镜像列表")
	rootCmd.Flags().StringArrayVarP(&runOpt.Skip, "skip", "", nil, "跳过的镜像列表")

	rootCmd.Flags().BoolVarP(&runOpt.OnlyPush, "push", "p", false, "只进行推送操作")
	rootCmd.Flags().StringArrayVarP(&runOpt.ImageFeature, "features", "t", []string{}, "镜像类型[bundle]")

	rootCmd.AddCommand(rule.RootCmd)
	rootCmd.AddCommand(center.RootCmd)
	rootCmd.AddCommand(registry.RootCmd)
}
